﻿using System;
using System.Collections;
using SolidEdgeGeometry;

namespace MultiConvert
{
    class SESheetMetalConverter : SEDocumentConverter 
    {
        private SolidEdgePart.SheetMetalDocument Document;        
        private SolidEdgeGeometry.Face Face = null;
        private String ToFile;
        
        public SESheetMetalConverter(Object SolidEdgeDoc, SEApplicationWrapper parent)
        {
            this.Application = parent;
            this.Document = (SolidEdgePart.SheetMetalDocument)SolidEdgeDoc;
            this.HighlightSets = this.Document.HighlightSets;            
        }

        internal override String convert(String ConvertMethod, String toFileName)
        {
            this.ConversionResult = Properties.Resources.MsgConvFailed;
            this.ToFile = toFileName;

            switch (ConvertMethod)
            {
                case "psm2dxf":

                    SolidEdgeGeometry.Body Body = null;                    
                    SolidEdgeGeometry.Edge Edge = null;
                    SolidEdgeGeometry.Edges Edges = null;
                    SolidEdgeGeometry.Vertex StartVertex = null; 
                    Array FacesArr = new Object[0];
                    Int32 NumFaces = 0;

                    try
                    {

                        if (this.Document.FlatPatternModels.Count != 0)
                        {
                            // Face aus Referenz von FlatPatternEdgebarFeatures zuweisen                       
                            SolidEdgePart.FlatPattern FlatPattern = (SolidEdgePart.FlatPattern)Document.FlatPatternEdgebarFeatures.Item(1);
                            if (FlatPattern.Reference is SolidEdgeGeometry.Face)
                            {
                                //entweder direkt, wenn bereits Fläche
                                Face = (SolidEdgeGeometry.Face)FlatPattern.Reference;
                            }
                            else if (FlatPattern.Reference is SolidEdgeGeometry.Edges)
                            {
                                //Falls Reference keine Fläche sondern Edges 
                                Edges = (SolidEdgeGeometry.Edges)FlatPattern.Reference;
                                Array FacesArr2 = new SolidEdgeGeometry.Face[3];
                                for (Int32 i = 0, m = 0; i <= 1; i++, m++)
                                {
                                    Edge = (SolidEdgeGeometry.Edge)Edges.Item(i);
                                    Edge.GetFaces(out NumFaces, ref FacesArr);
                                    FacesArr2.SetValue((SolidEdgeGeometry.Face)FacesArr.GetValue(0), i + m);
                                    FacesArr2.SetValue((SolidEdgeGeometry.Face)FacesArr.GetValue(1), i + m + 1);
                                }
                                Face = this.getMaxFace(FacesArr2);
                            }
                        }
                    }
                    catch {}

                    if (Face != null)
                    {
                        if (Face.Geometry is SolidEdgeGeometry.Plane)
                        {
                            this.saveDXF(Face, Properties.Resources.MsgConvByIgPlane);
                        }
                        else if (Face.Geometry is SolidEdgeGeometry.Cylinder)
                        {
                            // Geometriedaten der Reference von FlatPatternEdgebarFeatures ermitteln
                            Array axisVector = new Double[3];
                            Array basePoint = new Double[3];
                            Double radius;
                            ((SolidEdgeGeometry.Cylinder)Face.Geometry).GetCylinderData(ref basePoint, ref axisVector, out radius);

                            Double32 Radius = radius;                            
                            Double32[] AxisVector = new Double32[3];
                            AxisVector[0] = ((Double)axisVector.GetValue(0));
                            AxisVector[1] = ((Double)axisVector.GetValue(1));
                            AxisVector[2] = ((Double)axisVector.GetValue(2));
                            Double32[] BasePoint = new Double32[3];
                            BasePoint[0] = ((Double)basePoint.GetValue(0));
                            BasePoint[1] = ((Double)basePoint.GetValue(1));
                            BasePoint[2] = ((Double)basePoint.GetValue(2));                            //Geometriedaten von allen igCircles ermitteln und bei Gleichheit mit Geometriedaten der Reference DXF speichern
                            
                            Array AxisVector2 = new Double[3];
                            Array BasePoint2 = new Double[3];
                            Double Radius2;

                            Body = ((SolidEdgeGeometry.Body)(this.Document.Models.Item(1).Body));
                            Edges = (SolidEdgeGeometry.Edges)Body.get_Edges(FeatureTopologyQueryTypeConstants.igQueryAll);                            

                            for (Int32 k = 1; k <= Edges.Count; k++)
                            {
#if DEBUG
                                this.Application.RemoveHighlight();
#endif
                                SolidEdgeGeometry.Edge myEdge = (SolidEdgeGeometry.Edge)Edges.Item(k);
#if DEBUG
                                this.Application.Highlight(myEdge);
#endif
                                if (myEdge.Geometry is SolidEdgeGeometry.Circle)
                                {
                                    ((SolidEdgeGeometry.Circle)myEdge.Geometry).GetCircleData(ref BasePoint2, ref AxisVector2, out Radius2);                                  
                                    if ((Radius.Equals(Radius2)) &&
                                        BasePoint[0].Equals(BasePoint2.GetValue(0)) &&
                                        BasePoint[1].Equals(BasePoint2.GetValue(1)) &&
                                        BasePoint[2].Equals(BasePoint2.GetValue(2)) &&
                                        AxisVector[0].Equals(AxisVector2.GetValue(0)) &&
                                        AxisVector[1].Equals(AxisVector2.GetValue(1)) &&
                                        AxisVector[2].Equals(AxisVector2.GetValue(2)))
                                    {
                                        Edge = (SolidEdgeGeometry.Edge)Edges.Item(k);
                                        StartVertex = (SolidEdgeGeometry.Vertex)Edge.StartVertex;
                                        Edge.GetFaces(out NumFaces, ref FacesArr);
                                        try
                                        {
                                            this.saveDXF(this.getMaxFace(FacesArr), Edge, StartVertex, Properties.Resources.MsgConvByIgCylinder);
                                            break;
                                        }
                                        catch { }                                        
                                    }
                                }
                            }
                        }

                    }                    

                    //wenn DXF export nocht nicht erfolgt oder über Reference nicht möglich dann
                    //Ermittlung von Face über größte Fläche
                    if (this.ConversionResult == Properties.Resources.MsgConvFailed)
                    {
                        SolidEdgePart.Model Model;
                        Model = this.Document.Models.Item(1);                        
                        SolidEdgeGeometry.Body body = (SolidEdgeGeometry.Body)Model.Body;
                        SolidEdgeGeometry.Faces faces;
                        faces = (SolidEdgeGeometry.Faces)body.get_Faces(FeatureTopologyQueryTypeConstants.igQueryAll);
                        this.Face = this.getMaxFace(faces);
                        this.saveDXF(this.Face, Properties.Resources.MsgConvByMaxArea);
                    }
                    break;
                    
                case "psm2x_t":
                case "psm2igs":
                case "psm2jt":
                case "psm2stp":
            		this.ConversionResult = this.SaveAs( (SolidEdgeFramework.SolidEdgeDocument)this.Document, toFileName, ConvertMethod );                    
                    break;

                case "psm2jpg":
                    this.ConversionResult = this.SaveAsImage((SolidEdgeFramework.SolidEdgeDocument)this.Document, toFileName, ConvertMethod);
                    break;
                
                default:
                    this.ConversionResult = Properties.Resources.MsgNoConvImplemented;
                    break;
            }
            
            return this.ConversionResult;
        }

        private SolidEdgeGeometry.Face getMaxFace(Object faces)
        {
            SEFace maxFace = null;
            ArrayList FaceList = new ArrayList();

            if (faces is SolidEdgeGeometry.Faces)
            {
                SolidEdgeGeometry.Faces sefaces = (SolidEdgeGeometry.Faces)faces;
                for (Int32 i = 1; i <= sefaces.Count; i++)
                {
                    FaceList.Add(new SEFace((SolidEdgeGeometry.Face)sefaces.Item(i)));
                }
            }
            else if (faces is Array)
            {
                Array arrfaces = (Array)faces;
                foreach (SolidEdgeGeometry.Face face in arrfaces)
                {
                    FaceList.Add(new SEFace(face));
                }
            }

            if (this.Face != null)
            {
                foreach (SEFace face in FaceList)
                {
                    SolidEdgeGeometry.Face myface = (SolidEdgeGeometry.Face)face.getGeometry();

                    try
                    {
                        if (myface.Area.Equals(Face.Area))
                        {
                            maxFace = face;
                            break;
                        }

                    }
                    catch { }
                }
                
            }
            if (maxFace == null)
            {
                FaceList.Sort();
                maxFace = (SEFace)FaceList[0];
            }                      
#if DEBUG
            this.Application.RemoveHighlight();
            this.Application.Highlight(maxFace);
#endif 
            return (SolidEdgeGeometry.Face)maxFace.getGeometry();
        }                       
        private void saveDXF(SolidEdgeGeometry.Face face, String retVal)
        {
            SolidEdgeGeometry.Edges edges = (SolidEdgeGeometry.Edges)face.Edges;
            SolidEdgeGeometry.Edge edge;
            SolidEdgeGeometry.Vertex startvertex = null;
            ArrayList myEdges = new ArrayList(); 

            for (Int32 i = 1; i <= edges.Count; i++)
            {
                edge = (SolidEdgeGeometry.Edge)edges.Item(i);                
                myEdges.Add(new SEEdge(edge));
            }
            myEdges.Sort();            
            foreach (SEEdge seedge in myEdges)
            {
                try
                {
                    edge = (SolidEdgeGeometry.Edge)seedge.getGeometry();
                    startvertex = (SolidEdgeGeometry.Vertex)edge.StartVertex;
                    this.saveDXF(face, edge, startvertex, retVal);
                    break;
                }
                catch { }
            }            
        }
        private void saveDXF(SolidEdgeGeometry.Face face, SolidEdgeGeometry.Edge edge, SolidEdgeGeometry.Vertex startvertex, String retVal)
        {
#if DEBUG
            this.Application.RemoveHighlight();
            this.Application.Highlight(face);
            this.Application.Highlight(edge);
            this.Application.Highlight(startvertex);
#endif
            this.Document.Models.SaveAsFlatDXF(this.ToFile, face, edge, startvertex);
            this.ConversionResult = retVal;
        }
    }

    class SEFace : ISEGeometry
    {
        private SolidEdgeGeometry.Face myface;        
        private Double Area;
        public SEFace(SolidEdgeGeometry.Face face)
        {
            this.myface = face;
            this.Area = face.Area;
        }

        public int CompareTo(Object obj)
        {
            if (obj is SEFace)
            {
                if (this.Area < ((SEFace)obj).Area) return 1;
                else if (this.Area > ((SEFace)obj).Area) return -1;
                else return 0;
            }
            else
            {                
                return 2;
            }
        }
         
        public Object getGeometry()
        {
            return this.myface;
        }

    }
    class SEEdge : ISEGeometry 
    {
        private SolidEdgeGeometry.Edge myedge;
        private SolidEdgeGeometry.Vertex startvertex;
        private SolidEdgeGeometry.Vertex endvertex;
        private Double length = 0;
        
        public SEEdge(SolidEdgeGeometry.Edge edge)
        {
            this.myedge = edge;
            
            try
            {
                this.startvertex = (SolidEdgeGeometry.Vertex)edge.StartVertex;
                this.endvertex = (SolidEdgeGeometry.Vertex)edge.EndVertex;
                this.myedge.GetLengthAtParam(0, 1, out this.length);
            }
            catch { }
        }

        public int CompareTo(Object obj)
        {
            if (obj is SEEdge)
            {
                if (this.length < ((SEEdge)obj).length) return 1;
                else if (this.length > ((SEEdge)obj).length) return -1;
                else return 0;
            }
            else
            {                
                return 2;
            }
        }

        public Object getGeometry()
        {
            return this.myedge;
        }
    }
    
}
